package com.thinkersre.service;

//import com.thinkersre.dao.LoginTicketMapper;
import com.thinkersre.dao.UserMapper;
import com.thinkersre.entity.LoginTicket;
import com.thinkersre.entity.User;
import com.thinkersre.event.mail.Mail;
import com.thinkersre.event.mail.MailProducer;
import com.thinkersre.util.MailClient;
import com.thinkersre.util.RedisKeyUtil;
import com.thinkersre.util.ThinkersReConstant;
import com.thinkersre.util.ThinkersReUtil;
import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;



import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.thinkersre.util.RedisKeyUtil.getUserKey;

@Service
public class UserService implements ThinkersReConstant {

    @Resource
    private UserMapper userMapper;
    @Resource
    private MailClient mailClient;
    @Resource
    private MailProducer mailProducer;
    @Resource
    private TemplateEngine templateEngine;
//    @Resource
//    private LoginTicketMapper loginTicketMapper;
    @Value("${thinkersre.path.domain}")
    private String domain;
    @Resource
    private RedisTemplate redisTemplate;
    //项目名
    @Value("${server.servlet.context-path}")
    private String contextpath;

    public User findUserById(int id){
//       return userMapper.selectById(id);
        User user = getCache(id);
        if (user == null){
            user = initCache(id);

        }
        return user;
    }

    //通过邮箱找user
    public User findUserByEmail(String email){
        return userMapper.selectByEmail(email);
    }


    //注册功能
    public Map<String,Object> register(User user){
        //设定返回参数，封装数据
        Map<String,Object> map = new HashMap<>();
        //判断是否为空
        if(user == null){
            throw new IllegalArgumentException("参数不能为空!");
        }
        //判断用户名是否为空值
        if(StringUtils.isBlank(user.getUsername())){
            //存放错误信息等待调用
            map.put("usernameMsg","用户名不能为空!");
            return map;
        }
        //判断密码是否为空值
        if(StringUtils.isBlank(user.getPassword())){
            //存放错误信息等待调用
            map.put("passwordMsg","密码不能为空!");
            return map;
        }
        //判断邮箱是否为空值
        if(StringUtils.isBlank(user.getEmail())){
            //存放错误信息等待调用
            map.put("emailMsg","邮箱不能为空!");
            return map;
        }
        //验证账号
        User userVerify = userMapper.selectByName(user.getUsername());
        //检查账号是否已存在
        if(userVerify != null){
            map.put("usernameMsg","已存在账户");
            return map;
        }
        //检查邮箱是否已存在
        userVerify = userMapper.selectByEmail(user.getEmail());
        if(userVerify != null){
            map.put("emailMsg","该邮箱已被注册");
            return map;
        }
        //注册用户
        //加盐
        user.setSalt(ThinkersReUtil.getUUID().substring(0,5));
        //密码加密
        user.setPassword(ThinkersReUtil.md5encrypt(user.getPassword()+user.getSalt()));
        //设置默认类型
        user.setType(0);
        //设置默认状态
        user.setStatus(0);;
        //设置激活码
        user.setActivationCode(ThinkersReUtil.getUUID());
        //设置注册时间
        user.setCreateTime(new Date());
        //设置初始头像
        user.setHeaderUrl(String.format("http://thinkersre.com/UserHeader/%d.png",new Random().nextInt(17)));
        userMapper.insertUser(user);
        //激活邮件
        Context context = new Context();
        context.setVariable("email",user.getEmail());
        String url = domain + contextpath + "/activation/" + user.getId() + "/" + user.getActivationCode();
        context.setVariable("url",url);
        String content = templateEngine.process("/mail/activation",context);
        mailClient.sendMail(user.getEmail(),"激活邮件",content);
        return map;
    }



    public int activation(int userId, String code){
        User user = userMapper.selectById(userId);
        if(user.getStatus() == 1){
            return ACTIVATION_REPEAT;
        } else if (user.getActivationCode().equals(code)) {
            userMapper.updateStatus(userId,1);
            clearCache(userId);
            return ACTIVATION_SUCCESS;
        }else{
            return ACTIVATION_FAIL;
        }

    }
    public Map<String,Object> login(String username,String password,int expiredSeconds){
        Map<String,Object> map = new HashMap<>();
        //空值处理
        if(StringUtils.isBlank(username)){
            map.put("usernameMsg","用户名不能为空");
            return map;
        }if(StringUtils.isBlank(password)){
            map.put("passwordMsg","密码不能为空");
            return map;
        }
        //验证账户
        User user = userMapper.selectByName(username);
        if(user == null){
            map.put("usernameMsg","该账号不存在");
            return map;
        }
        //验证状态
        if(user.getStatus()==0){
            map.put("usernameMsg","该账号未激活");
            return map;
        }
        //验证密码
        password = ThinkersReUtil.md5encrypt(password+user.getSalt());
        if(!user.getPassword().equals(password)){
            map.put("passwordMsg","密码错误");
            return map;
        }
        //生成登陆凭证
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setUserId(user.getId());
        loginTicket.setStatus(0);
        loginTicket.setTicket(ThinkersReUtil.getUUID());
        loginTicket.setExpired(new Date(System.currentTimeMillis()+expiredSeconds * 1000L));
        String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket());
        redisTemplate.opsForValue().set(redisKey,loginTicket);
//        loginTicketMapper.insertLoginTicket(loginTicket);
        map.put("ticket",loginTicket.getTicket());
        return map;
    }

    public void logout(String ticket){
//        loginTicketMapper.updateStatus(ticket,1);
        String redisKey = RedisKeyUtil.getTicketKey(ticket);
        LoginTicket loginTicket =(LoginTicket) redisTemplate.opsForValue().get(redisKey);
        loginTicket.setStatus(1);
        redisTemplate.opsForValue().set(redisKey,loginTicket);

    }


    public void logoutByUserid( int id,int status){
        userMapper.updateStatusByUserid(id,status);
    }


    public LoginTicket findLoginTicket(String ticket){
//        return loginTicketMapper.selectByTicket(ticket);
        String redisKey = RedisKeyUtil.getTicketKey(ticket);
        return (LoginTicket) redisTemplate.opsForValue().get(redisKey);
    }

    public int updateHeader(int userId,String headerUrl){
        int rows = userMapper.updateHeader(userId, headerUrl);
        clearCache(userId);
        return rows;
    }
    //修改密码时，判断所传参数是否为空
    public Map<String,Object> passwordVerify(String originPassword, String typePassword, String retypePassword){
        //创建返回对象
        Map<String,Object> map = new HashMap<>();
        //判断原密码是否为空是否小于8位，传入错误信息
        if (StringUtils.isBlank(originPassword)){
            map.put("originPMsg","原密码不能为空");
        }else if (originPassword.length()<8){
            map.put("originPMsg","密码长度不能小于8位");
        }
        //判断新密码是否为空，是否小于8位
        if(StringUtils.isBlank(typePassword)){
            map.put("typePMsg","新密码不能为空");
        }else if(typePassword.length()<8){
            map.put("typePMsg","密码长度不能小于8位");
        }
        //判断再次输入的新密码是否为空，是否小于8位
        if (StringUtils.isBlank(retypePassword)){
            map.put("retypePMsg","再次输入不能为空");
        } else if (retypePassword.length() < 8) {
            map.put("retypePMsg","密码长度不能小于8位");
        }
        //判断新密码与再次输入的新密码是否相同
        if(!typePassword.equals(retypePassword)){
            map.put("PPverify","两次新密码输入不同，请检查");
        }
        return map;
    }
    //开始修改密码
    public void updatePassword(int userId, String password) {
        userMapper.updatePassword(userId, password);
    }


    //通过邮箱更新密码
    public void updatePasswordByEmail(String email,String password){
        User user = userMapper.selectByEmail(email);
        String salt = user.getSalt();
        String newPassword = ThinkersReUtil.md5encrypt(password+salt);
        userMapper.updatePasswordByEmail(email,newPassword);
    }

    //对原密码与输入密码进行校验
//    public boolean judgeTwoPassword(String password,String inputPassword){
//        if(password.equals(inputPassword)){
//            return true;
//        }
//
//        return false;
//
//    }

    public User findUserByName(String username){
        return userMapper.selectByName(username);
    }

    //优先从缓存中取值
    private User getCache(int userId){
        String redisKey = getUserKey(userId);
        //序列化为字符串
        return (User)redisTemplate.opsForValue().get(redisKey);
    }
    //取不到时初始化缓存数据
    private User initCache(int userId){
        User user = userMapper.selectById(userId);
        String redisKey = getUserKey(userId);
        redisTemplate.opsForValue().set(redisKey,user,3600, TimeUnit.SECONDS);
        return user;
    }

    //数据变更时清除缓存数据
    private void clearCache(int userId){
        String redisKey = getUserKey(userId);
        redisTemplate.delete(redisKey);
    }


    public Collection<? extends GrantedAuthority> getAuthorities(int userId){
        User user = findUserById(userId);
        List<GrantedAuthority> grantedAuthorityList = new ArrayList<>();
        grantedAuthorityList.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                switch(user.getType()){
                    case 1:
                        return  AUTHORITY_ADMIN;
                    case 2:
                        return AUTHORITY_MODERATOR;
                    default:
                        return AUTHORITY_USER;
                }
            }
        });
        return grantedAuthorityList;
    }




/* 以下为测试代码 */
/* 样式开始 ===============================================================================*/
//获取验证码/重置密码//
    public Map<String, Object> getCode(String email) {
        Map<String,Object> map = new HashMap<>();


        if (StringUtils.isBlank(email)) {

            map.put("emailMsg","邮箱不能为空!");
            return map;
        }
        if (email.length() <= 11) {

            map.put("emailMsg","邮箱格式错误!");
            return map;
        }

        User user = userMapper.selectByEmail(email);

        if (user == null) {
            map.put("emailMsg","该邮箱未注册!");
            return map;
        }
        if (user.getStatus() == 0){
            map.put("emailMsg","该邮箱还未激活!");
            return map;
        }

        String code = ThinkersReUtil.getUUID().substring(0, 6);
        map.put("code", code);
        // 激活邮件
        Context context = new Context();
        context.setVariable("email",user.getEmail());

        context.setVariable("code",code);

        String content = templateEngine.process("/mail/forget",context);

        Mail mail = new Mail();
        mail.setTo(user.getEmail());
        mail.setContent(content);
        mail.setSubject("修改您的IT世界密码");

        try {
            mailProducer.fireMail(mail);
        } catch (Exception e) {
            map.put("emailMsg", "发送失败,请稍后再试!");
            return map;
        }
        map.put("expirationTime", LocalDateTime.now().plusMinutes(5));
        map.put("cd", LocalDateTime.now().plusMinutes(1));
        return map;
    }






//重置密码提示//优先级最高的信息展示
    public Map<String, Object> resetPasswordMsg(String password, String code) {
        Map<String, Object> map = new HashMap<>();

        if (code.isEmpty()) {
            map.put("codeMsg", "验证码不能为空!");
            return map;
        }
        if (password.isEmpty()) {
            map.put("passwordMsg", "密码不能为空!");
            return map;
        }

        if (password.length() < 8) {
            map.put("passwordMsg", "密码长度不能小于8位!");
            return map;
        }

        return map;
    }
}
